// $Id: output.hpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#ifndef XPGEN_OUTPUT_HPP
#define XPGEN_OUTPUT_HPP

#include <set>
#include <string>
#include <vector>
#include <boost/filesystem/path.hpp>

namespace xpgen {

struct module_decl;
struct interface_decl;

class output
{
public:
    explicit output(output* prev = 0);
    virtual ~output();

    // options
    bool verbose;
    unsigned indent_size;
    boost::filesystem::path input_file; // just for informational
    boost::filesystem::path output_dir;
    boost::filesystem::path output_file; // may not be used
    std::string output_ext;

    std::set<std::string> included_interface_qnames;
    std::set<std::string> excluded_interface_qnames;

    bool enabled() const
    {
        return enabled_;
    }

    void enable()
    {
        enabled_ = true;
    }

    void disable()
    {
        enabled_ = false;
    }

    void chain_output(output* next);
    virtual void do_all(module_decl* module);

protected:
    // Return true if the interface is to be output
    // By default, included, non-root resolved interfaces are to be output
    virtual bool filter_interface(interface_decl* itf);

    // Process order is:
    // do_reset -> do_prolog -> do_interface(s) -> do_epilogue
    virtual void do_reset();
    virtual void do_prologue();
    virtual void do_epilogue();
    virtual void do_interface(interface_decl* itf) = 0;

protected:
    module_decl* module() const
    {
        return module_;
    }

    const std::string& indent() const
    {
        return indent_;
    }

    const std::vector<std::string>& ns_stack() const
    {
        return ns_stack_;
    }

    void reset_indent();
    void push_indent(unsigned count = 1);
    void pop_indent(unsigned count = 1);

    void reset_ns();
    void push_ns(const std::string& ns_name);
    void pop_ns();

    // Return true if the interface is to be included
    bool is_interface_included(interface_decl* itf) const;

    output* prev() const
    {
        return prev_;
    }

    output* next() const
    {
        return next_;
    }

private:
    void reset();

    bool enabled_;
    output* prev_;
    output* next_;

    // State info
    module_decl* module_;
    std::string indent_;
    std::vector<std::string> ns_stack_;
};

} // namespace xpgen

#endif // XPGEN_OUTPUT_HPP
